package org.jsola.hr.service.impl;

import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.jsola.core.Page;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.common.NumberKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.ISocDispatchCompanyDAO;
import org.jsola.hr.dto.SocDispatchCompanyAddDTO;
import org.jsola.hr.dto.SocDispatchCompanyUpdateDTO;
import org.jsola.hr.entity.SocDispatchCompanyDO;
import org.jsola.hr.entity.SocDispatchCompanyEmpDO;
import org.jsola.hr.entity.SocDispatchDO;
import org.jsola.hr.provider.IPermissionProviderService;
import org.jsola.hr.query.SocDispatchCompanyQuery;
import org.jsola.hr.query.SocDispatchEmpAddQuery;
import org.jsola.hr.query.SocDispatchEmpLessQuery;
import org.jsola.hr.service.ISocDispatchCompanyEmpService;
import org.jsola.hr.service.ISocDispatchCompanyService;
import org.jsola.hr.service.ISocDispatchEmpAddService;
import org.jsola.hr.service.ISocDispatchEmpLessService;
import org.jsola.hr.vo.*;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static org.jsola.hr.constant.HrConstants.SUPREME;

/**
 * 社保派单公司记录表
 *
 * @author zhr
 */
@Service("hrSocDispatchCompanyServiceImpl")
public class SocDispatchCompanyServiceImpl implements ISocDispatchCompanyService {

    @Autowired
    private ISocDispatchCompanyDAO socDispatchCompanyDAO;

    @Autowired
    private ISocDispatchCompanyEmpService socDispatchCompanyEmpService;

    @Autowired
    private ISocDispatchEmpAddService socDispatchEmpAddService;

    @Autowired
    private ISocDispatchEmpLessService socDispatchEmpLessService;

    @Autowired
    private IPermissionProviderService permissionProviderService;

    private final BigDecimal decimal0 = new BigDecimal(0);

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public SocDispatchCompanyVO save(SocDispatchCompanyAddDTO socDispatchCompanyAddDTO, TokenUser tokenUser) {
        // 转DO
        SocDispatchCompanyDO socDispatchCompanyDO = socDispatchCompanyAddDTO.to(SocDispatchCompanyDO.class);

        // 增加名称
        addSocDispatchName(socDispatchCompanyDO, tokenUser.getSiteId());

        // 保存
        socDispatchCompanyDO = save(socDispatchCompanyDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return socDispatchCompanyDO.to(SocDispatchCompanyVO.class);
    }

    /**
     * 增加名称
     *
     * @param socDispatchCompanyDO 派单记录
     * @param siteId               站点id
     */
    private void addSocDispatchName(SocDispatchCompanyDO socDispatchCompanyDO, String siteId) {
        if (StringUtils.isNotEmpty(socDispatchCompanyDO.getName())) {
            return;
        }
        // 当月已有的
        List<SocDispatchCompanyDO> list = listByYearAndMonth(socDispatchCompanyDO.getYear(),
                socDispatchCompanyDO.getMonth(), socDispatchCompanyDO.getCompanyId(),
                Collections.singletonList(socDispatchCompanyDO.getChildCompanyId()), siteId);
        // 当前次数
        int nowCount = list.size() + 1;
        String numStr = NumberKit.formatNumber(nowCount);
        String name = socDispatchCompanyDO.getYear() + "年" + Integer.valueOf(socDispatchCompanyDO.getMonth()) + "月" + " 第" + numStr + "次接单";
        if (socDispatchCompanyDO.getAddOrLess()) {
            name = name + "（增员）";
        } else {
            name = name + "（减员）";
        }
        socDispatchCompanyDO.setName(name);
    }

    /**
     * 根据年月获取派单记录
     *
     * @param companyId          公司id
     * @param year               年
     * @param month              月
     * @param childCompanyIdList 站点id
     * @return 派单记录
     */
    private List<SocDispatchCompanyDO> listByYearAndMonth(String year, String month, String companyId, List<String> childCompanyIdList, String siteId) {
        if (CollectionUtils.isEmpty(childCompanyIdList)) {
            return new ArrayList<>();
        }
        Example example = new Example(SocDispatchCompanyDO.class);
        example.and()
                .andEqualTo("companyId", companyId)
                .andEqualTo("year", year)
                .andEqualTo("month", month)
                .andEqualTo("siteId", siteId);

        if (CollectionUtils.isEmpty(childCompanyIdList)) {
            example.and().andIsNull("childCompanyId");
        } else {
            if (!childCompanyIdList.contains(SUPREME)) {
                example.and().andIn("childCompanyId", childCompanyIdList);
            }
        }

        return socDispatchCompanyDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(SocDispatchCompanyUpdateDTO socDispatchCompanyUpdateDTO, TokenUser tokenUser) {
        //转DO
        SocDispatchCompanyDO socDispatchCompanyDO = socDispatchCompanyUpdateDTO.to(SocDispatchCompanyDO.class);
        //根据主键更新，只更新非null值
        return updateByIdSelective(socDispatchCompanyDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... socDispatchCompanyIds) {
        return deleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) socDispatchCompanyIds);
    }


    @Override
    public SocDispatchCompanyVO selectById(String socDispatchCompanyId, String siteId) {
        SocDispatchCompanyDO socDispatchCompanyDO = selectDOById(socDispatchCompanyId, siteId);
        if (socDispatchCompanyDO == null) {
            return null;
        }
        return socDispatchCompanyDO.to(SocDispatchCompanyVO.class);
    }

    @Override
    public List<SocDispatchCompanyListVO> select(SocDispatchCompanyQuery socDispatchCompanyQuery, String siteId) {
        List<SocDispatchCompanyDO> socDispatchCompanyDOList = selectDO(socDispatchCompanyQuery, siteId);
        if(CollectionUtils.isEmpty(socDispatchCompanyDOList)) {
            return socDispatchCompanyDOList == null ? null : new ArrayList<>();
        }
        return socDispatchCompanyDOList.stream()
                .map(socDispatchCompanyDO -> socDispatchCompanyDO.to(SocDispatchCompanyListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(SocDispatchCompanyQuery socDispatchCompanyQuery, String siteId) {
        Example example = buildExample(socDispatchCompanyQuery,siteId);
        return socDispatchCompanyDAO.selectCountByExample(example);
    }

    @Override
    public Page<SocDispatchCompanyListVO> selectPage(SocDispatchCompanyQuery socDispatchCompanyQuery, TokenUser tokenUser) {
        Example example = buildExample(socDispatchCompanyQuery, tokenUser.getSiteId());

        // 获取当前用户所属分公司
        List<String> childCompanyIdList = permissionProviderService.listChildCompanyId(tokenUser);
        if (CollectionUtils.isEmpty(childCompanyIdList)) {
            example.and().andIsNull("childCompanyId");
        } else {
            if (!childCompanyIdList.contains(SUPREME)) {
                // 非主公司
                example.and().andIn("childCompanyId", childCompanyIdList);
            }
        }

        Page<SocDispatchCompanyDO> page = socDispatchCompanyDAO.selectPageByExample(example,
                socDispatchCompanyQuery.getPageNo(),
                socDispatchCompanyQuery.getPageSize());


        Page<SocDispatchCompanyListVO> pageVo = page.to(SocDispatchCompanyListVO.class);
        if (!CollectionUtils.isEmpty(pageVo.getEntities())) {
            pageVo.getEntities().parallelStream().forEach(
                    // 获取统计数据
                    socDispatch -> {
                        SocDispatchNumber socDispatchNumber = new SocDispatchNumber();

                        // 人员统计
                        getEmpSum(socDispatchNumber, tokenUser.getSiteId(), socDispatch.getId());

                        // 放值
                        int numAll = socDispatchNumber.getNumAll();
                        int numHasFinish = socDispatchNumber.getNumHasFinish();
                        int numError = socDispatchNumber.getNumError();
                        socDispatch.setNumAll(numAll);
                        socDispatch.setNumNotFinish(socDispatchNumber.getNumNotFinish());
                        socDispatch.setNumHasFinish(numHasFinish);
                        socDispatch.setNumError(numError);

                        socDispatch.setIsFinishAll(numHasFinish + numError == numAll);
                    }
            );
        }
        return pageVo;
    }


    @Override
    public SocDispatchCompanyDO selectDOById(String socDispatchCompanyId, String siteId) {
        return listById(socDispatchCompanyId, siteId);
    }

    @Override
    public List<SocDispatchCompanyDO> selectDO(SocDispatchCompanyQuery socDispatchCompanyQuery, String siteId) {
        Example example = buildExample(socDispatchCompanyQuery,siteId);
        return socDispatchCompanyDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void addCompanySocDispatch(SocDispatchDO socDispatch, List<String> socDispatchEmpIdList, TokenUser tokenUser) {
        ParamException.notEmpty(socDispatchEmpIdList, "社保派单分配到公司,请传递要分配到该公司的员工");
        ParamException.notNull(socDispatch, "社保派单分配到公司,总派单记录不能为空");

        SocDispatchCompanyAddDTO addDTO = new SocDispatchCompanyAddDTO();
        addDTO.setYear(socDispatch.getYear());
        addDTO.setMonth(socDispatch.getMonth());
        addDTO.setCompanyId(socDispatch.getCompanyId());
        addDTO.setAddOrLess(socDispatch.getAddOrLess());
        addDTO.setSocDispatchId(socDispatch.getId());
        // 保存
        SocDispatchCompanyVO socDispatchCompany = save(addDTO, tokenUser);

        //  排到该公司的员工
        List<SocDispatchCompanyEmpDO> companyEmpList = socDispatchEmpIdList.parallelStream().map(
                socDispatchEmpId -> {
                    // 构建保存
                    SocDispatchCompanyEmpDO companyEmp = new SocDispatchCompanyEmpDO();
                    companyEmp.setSocDispatchId(socDispatch.getId());
                    companyEmp.setAddOrLess(socDispatch.getAddOrLess());
                    companyEmp.setSocDispatchCompanyId(socDispatchCompany.getId());
                    companyEmp.setCompanyId(socDispatch.getCompanyId());
                    companyEmp.setSocDispatchEmpId(socDispatchEmpId);
                    companyEmp.preInsert(tokenUser.getUserId());
                    companyEmp.setSiteId(tokenUser.getSiteId());

                    return companyEmp;
                }
        ).collect(Collectors.toList());
        // 批量保存
        socDispatchCompanyEmpService.batchSave(companyEmpList, tokenUser);
    }

    @Data
    private class SocDispatchNumber {
        int numAll = 0;
        int numHasFinish = 0;
        int numNotFinish = 0;
        int numError = 0;
        int numImportError = 0;
        int numImportNoError = 0;

        BigDecimal personalSocAmount = decimal0;
        BigDecimal personalPfAmount = decimal0;
        BigDecimal personalAllAmount = decimal0;
        BigDecimal companySocAmount = decimal0;
        BigDecimal companyPfAmount = decimal0;
        BigDecimal companyAllAmount = decimal0;
        BigDecimal allAmount = decimal0;
    }

    /**
     * 获取人员统计
     *
     * @param socDispatchNumber  数量统计
     * @param siteId             站点id
     * @param dispatchCompanyIds 派单记录id
     */
    private void getEmpSum(SocDispatchNumber socDispatchNumber, String siteId, String... dispatchCompanyIds) {
        if (dispatchCompanyIds == null || dispatchCompanyIds.length == 0) {
            return;
        }
        List<SocDispatchCompanyEmpDetailsVO> detailList = socDispatchCompanyEmpService.listBySocDispatchCompanyIds(siteId, dispatchCompanyIds);

        if (!CollectionUtils.isEmpty(detailList)) {
            detailList.forEach(
                    // 根据状态增加员工统计数量
                    empDetail -> {
                        socDispatchNumber.setNumAll(socDispatchNumber.getNumAll() + 1);

                        // 派单状态(0:未完成,1:已完成,2:错误)
                        if (empDetail.getStatus() == 0) {
                            socDispatchNumber.setNumNotFinish(socDispatchNumber.getNumNotFinish() + 1);
                        } else if (empDetail.getStatus() == 1) {
                            socDispatchNumber.setNumHasFinish(socDispatchNumber.getNumHasFinish() + 1);
                        } else if (empDetail.getStatus() == 2) {
                            socDispatchNumber.setNumError(socDispatchNumber.getNumError() + 1);
                        }

                        // 统计
                        socDispatchNumber.setPersonalSocAmount(NumberKit.decimalAdd(socDispatchNumber.getPersonalSocAmount(), empDetail.getPersonalSocAmount()));
                        socDispatchNumber.setPersonalPfAmount(NumberKit.decimalAdd(socDispatchNumber.getPersonalPfAmount(), empDetail.getPersonalPfAmount()));
                        socDispatchNumber.setCompanySocAmount(NumberKit.decimalAdd(socDispatchNumber.getCompanySocAmount(), empDetail.getCompanySocAmount()));
                        socDispatchNumber.setCompanyPfAmount(NumberKit.decimalAdd(socDispatchNumber.getCompanyPfAmount(), empDetail.getCompanyPfAmount()));
                    }
            );
            BigDecimal personalAllAmount = NumberKit.decimalAdd(socDispatchNumber.getPersonalSocAmount(), socDispatchNumber.getPersonalPfAmount());
            BigDecimal companyAllAmount = NumberKit.decimalAdd(socDispatchNumber.getCompanySocAmount(), socDispatchNumber.getCompanyPfAmount());
            BigDecimal allAmount = NumberKit.decimalAdd(personalAllAmount, companyAllAmount);

            socDispatchNumber.setPersonalAllAmount(personalAllAmount);
            socDispatchNumber.setCompanyAllAmount(companyAllAmount);
            socDispatchNumber.setAllAmount(allAmount);
        }
    }

    @Override
    public SocDispatchCompanyDetailsVO findCompanyDetailsById(String socDispatchCompanyId, String siteId) {
        SocDispatchCompanyDO socDispatchCompanyDO = selectDOById(socDispatchCompanyId, siteId);
        ParamException.notNull(socDispatchCompanyDO, "公司派单记录不存在或已删除");
        // 实体转换
        SocDispatchCompanyDetailsVO details = socDispatchCompanyDO.to(SocDispatchCompanyDetailsVO.class);

        SocDispatchNumber socDispatchNumber = new SocDispatchNumber();

        // 增加增员的人员统计
        getEmpSum(socDispatchNumber, siteId, details.getId());

        // 放值
        details.setNumAll(socDispatchNumber.getNumAll());
        details.setNumHasFinish(socDispatchNumber.getNumHasFinish());
        details.setNumNotFinish(socDispatchNumber.getNumNotFinish());
        details.setNumError(socDispatchNumber.getNumError());
        details.setPersonalSocAmount(socDispatchNumber.getPersonalSocAmount());
        details.setPersonalPfAmount(socDispatchNumber.getPersonalPfAmount());
        details.setCompanySocAmount(socDispatchNumber.getCompanySocAmount());
        details.setCompanyPfAmount(socDispatchNumber.getCompanyPfAmount());
        details.setPersonalAllAmount(socDispatchNumber.getPersonalAllAmount());
        details.setCompanyAllAmount(socDispatchNumber.getCompanyAllAmount());
        details.setAllAmount(socDispatchNumber.getAllAmount());

        return details;
    }

    @Override
    public Page<SocDispatchEmpAddListVO> pageEmpAdd(SocDispatchEmpAddQuery socDispatchEmpAddQuery, String socDispatchCompanyId, String siteId) {
        // 校验和获取
        SocDispatchCompanyDO socDispatchCompanyDO = checkAndGet(socDispatchCompanyId, siteId);

        socDispatchEmpAddQuery.setSocDispatchId(socDispatchCompanyDO.getSocDispatchId());
        socDispatchEmpAddQuery.setAssignCompanyId(socDispatchCompanyDO.getChildCompanyId());
        return socDispatchEmpAddService.selectPage(socDispatchEmpAddQuery, siteId);
    }

    private SocDispatchCompanyDO checkAndGet(String socDispatchCompanyId, String siteId) {
        SocDispatchCompanyDO socDispatchCompanyDO = selectDOById(socDispatchCompanyId, siteId);
        ParamException.notNull(socDispatchCompanyDO, "公司派单记录不存在或已删除");
        return socDispatchCompanyDO;
    }

    @Override
    public Page<SocDispatchEmpLessListVO> pageEmpLess(SocDispatchEmpLessQuery socDispatchEmpLessQuery, String socDispatchCompanyId, String siteId) {
        // 校验和获取
        SocDispatchCompanyDO socDispatchCompanyDO = checkAndGet(socDispatchCompanyId, siteId);
        socDispatchEmpLessQuery.setSocDispatchId(socDispatchCompanyDO.getSocDispatchId());
        socDispatchEmpLessQuery.setAssignCompanyId(socDispatchCompanyDO.getChildCompanyId());

        return socDispatchEmpLessService.selectPage(socDispatchEmpLessQuery, siteId);
    }

    /**
     * 根据查询参数，构建example

     * @param socDispatchCompanyQuery 查询参数
     * @param siteId 所属站点id
     * @return example
     */
    private Example buildExample(SocDispatchCompanyQuery socDispatchCompanyQuery, String siteId) {
        Example example = new Example(SocDispatchCompanyDO.class);
        example.and()
                .andEqualTo("siteId", siteId);
        if (socDispatchCompanyQuery.getYear() != null) {
            example.and().andEqualTo("year", socDispatchCompanyQuery.getYear());
        }
        if (socDispatchCompanyQuery.getMonth() != null) {
            example.and().andEqualTo("month", socDispatchCompanyQuery.getMonth());
        }
        if (socDispatchCompanyQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", socDispatchCompanyQuery.getCompanyId());
        }
        if (socDispatchCompanyQuery.getName() != null) {
            example.and().andEqualTo("name", socDispatchCompanyQuery.getName());
        }
        if (socDispatchCompanyQuery.getAddOrLess() != null) {
            example.and().andEqualTo("addOrLess", socDispatchCompanyQuery.getAddOrLess());
        }
        if (socDispatchCompanyQuery.getSocDispatchId() != null) {
            example.and().andEqualTo("socDispatchId", socDispatchCompanyQuery.getSocDispatchId());
        }
        if (socDispatchCompanyQuery.getChildCompanyId() != null) {
            example.and().andEqualTo("childCompanyId", socDispatchCompanyQuery.getChildCompanyId());
        }
        // 排序
        ExampleKit.setExampleOrder(example,socDispatchCompanyQuery.getOrders());
        return example;
    }
}




